﻿
namespace Sai.Core.Rules
{
    using Sai.Core.Introspection;
    using System.Collections.Generic;
    using System.Linq;

    internal class FieldDifferenceReporter
    {
        public FieldDifferenceReporter(ITypeDifference typeDifference)
        {
            this.TypeDifference = typeDifference;
        }

        private ITypeDifference TypeDifference { get; set; }

        public void ReportOnObsoleteFields(IEnumerable<FieldDeclaration> fields, TypeChangeReason reason)
        {
            var obsolete = fields.FindObsoleteMembers();

            foreach (var obs in obsolete)
            {
                this.TypeDifference.IdentifiedChange(
                    new UnaryTypeChange(
                        reason,
                        obs,
                        obs.ObsoleteReason
                        ));
            }
        }

        public void ReportOnRemovedFields(IEnumerable<FieldDeclaration> wasFields, IEnumerable<FieldDeclaration> nowFields, TypeChangeReason reason)
        {
            var removed = nowFields.FindRemovedMembers(wasFields);

            foreach (var remove in removed)
            {
                this.TypeDifference.IdentifiedChange(
                    new UnaryTypeChange(
                        reason,
                        remove
                        ));
            }

        }

        public void ReportOnAddedFields(IEnumerable<FieldDeclaration> wasFields, IEnumerable<FieldDeclaration> nowFields, TypeChangeReason reason)
        {
            var added = nowFields.FindAddedMembers(wasFields);

            foreach (var add in added)
            {
                this.TypeDifference.IdentifiedChange(
                    new UnaryTypeChange(
                        reason,
                        add
                        ));
            }

        }

        public void ReportOnChangedFields(IEnumerable<FieldDeclaration> wasFields, IEnumerable<FieldDeclaration> nowFields, TypeChangeReason reason)
        {
            // fields changing type
            var commonFields = nowFields.FindMatchingMembers(wasFields);

            // look at common fields
            if (commonFields.Any())
            {
                foreach (var field in commonFields)
                {
                    FieldDeclaration oldField = field.Item1;
                    FieldDeclaration newField = field.Item2;

                    if (oldField != null && newField != null)
                    {
                        if (oldField.TypeName != newField.TypeName)
                        {
                            // property type has changed.
                            this.TypeDifference.IdentifiedChange(
                                new BinaryTypeChange(
                                    reason,
                                    oldField,
                                    newField,
                                    string.Format("Changed type from {0} to {1}", oldField.TypeName, newField.TypeName)
                                ));
                        }
                    }
                }
            }
        }
    }
}
